package edu.cuit.avatar.thread;

import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author <a href="mailto:1020zhaodan@163.com">Adan</a>
 * @version 1.0
 * @date 2025/7/16 14:50
 */
public class ThreadCooperation {
    private static Account account = new Account();
    private static class Account{
        private Lock lock = new ReentrantLock(true);
        //创建锁上的条件用于线程间的通信
        private Condition newDeposit = lock.newCondition();
        //账户余额
        private int balance = 0;

        public int getBalance() {
            return balance;
        }

        public void deposit(int amount){
            //对临界区进行加锁
            lock.lock();
            try{
                balance += amount;
                System.out.println("存入一笔金额:" + amount);
                //唤醒正在等待的线程
                newDeposit.signal();
            } finally {
                //释放锁
                lock.unlock();
            }
        }

        public void withdraw(int amount){
            //对临界区进行加锁
            lock.lock();
            try{
                //余额不足，取款任务必须等待(一个条件对应一个锁。在等待和通知状态之前，线程必须先获取该条件的锁)
                while (amount > balance) {
                    System.err.println("余额不足,等待存款任务的完成.....");
                    newDeposit.await();
                }
                balance -= amount;
                System.out.println("取款完成，取款金额:" + amount);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                //释放锁
                lock.unlock();
            }
        }
    }

    /**
     * 取款任务:不停的取随机金额
     */
    private static class WithdrawTask implements Runnable{
        @Override
        public void run() {
            try {
                while (true){
                    int amount = (int)(Math.random() * 1000);
                    account.withdraw(amount);
                    Thread.sleep(5);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 取款任务:不停的取随机金额
     */
    private static class DepositTask implements Runnable{
        @Override
        public void run() {
            try {
                while (true){
                    int amount = (int)(Math.random() * 500);
                    account.deposit(amount);
                    Thread.sleep(5);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        var executor = Executors.newFixedThreadPool(2);
        executor.execute(new WithdrawTask());
        executor.execute(new DepositTask());

        executor.shutdown();
    }
}
